package com.bi.dataDmTrans.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bi.dataDmTrans.entity.DataItem;
import com.bi.dataDmTrans.entity.DataItem1;
import com.bi.dataDmTrans.mapper.DataItemMapper;
import dm.jdbc.filter.stat.json.JSONArray;
import dm.jdbc.filter.stat.json.JSONException;
import dm.jdbc.filter.stat.json.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;

import org.springframework.http.*;

@Service
@Slf4j
public class DataService {

    @Autowired
    private DataItemService dataItemService;

    @Autowired
    private DataItem1Service dataItem1Service;

    @Autowired
    private ExecutorService executorService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private TokenService tokenService;

    private static final int PAGE_SIZE = 200;

    // 清空表并开始抓取数据
    @Async
    public void fetchDataAndSave() {
        // 1. 清空表
        LambdaQueryWrapper<DataItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DataItem::getEtlDate, LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        queryWrapper.isNotNull(DataItem::getId);
        dataItemService.remove(queryWrapper);
        // 2. 获取token
        AtomicReference<String> token = new AtomicReference<>();
//        try {
//            token.set(new String(Files.readAllBytes(Paths.get("/opt/software/etlforeign/token/token.txt"))).trim());
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
        token.set(tokenService.getToken("", null));
        // 3. 获取接口的总记录数
        int totalData = getTotalDataCount(token.get());
        int totalPages = (totalData + PAGE_SIZE - 1) / PAGE_SIZE;

        // 4. 创建并发任务
        List<Callable<Void>> tasks = new ArrayList<>();
        for (int page = 1; page <= totalPages; page++) {
            final int pageNum = page;
            tasks.add(() -> {
                // 5. 分页获取数据
                log.info("开始添加任务,分页:{},数据量:{},总页数:{}", pageNum, totalData, totalPages);
                List<DataItem> data = fetchDataFromAPI(pageNum, PAGE_SIZE, token.get());
                log.info("data:{}", data);
                // 6. 保存数据到数据库
                dataItemService.saveDataToDatabase(data);
                log.info("任务完成,分页:{}", pageNum);
                return null;
            });
        }

        try {
            log.info("开始执行任务");
            // 7. 执行所有任务
            executorService.invokeAll(tasks);

            // 8. 所有任务完成后更新ETL日期
            updateEtlDate(0);
            log.info("任务执行结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private List<DataItem> fetchDataFromAPI(int pageNum, int pageSize, String token) {
        String apiUrl = "http://10.210.31.9:9033/apis/open/esi/smpcsmc/qrySupplierProdListDataLake";
        HttpHeaders headers = new HttpHeaders();

        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_JSON);

        JSONObject request = new JSONObject();
        request.put("extOid", 1);
        request.put("clientId", "117158@118092");
        request.put("pageNo", pageNum);
        request.put("pageSize", pageSize);
        HttpEntity<String> entity = new HttpEntity<>(request.toString(), headers);
        String responseJson = restTemplate.postForObject(apiUrl, entity, String.class);
        JSONObject response = new JSONObject(responseJson);
        System.out.println(response);
        JSONArray rows = response.getJSONObject("data").getJSONArray("rows");

        // 将返回的JSON数据转换为DataItem列表
        List<DataItem> dataItems = new ArrayList<>();
        for (int i = 0; i < rows.length(); i++) {
            JSONObject jsonObject = rows.getJSONObject(i);
            DataItem dataItem = new DataItem();
            dataItem.setProdinfoId(jsonObject.getLong("prodinfoId"));
            dataItem.setMatTrademark(jsonObject.getString("matTrademark"));
            dataItem.setMatcateryCode(jsonObject.getString("matcateryCode"));
            dataItem.setMatcateryName(jsonObject.getString("matcateryName"));
            dataItem.setSupinfoId(jsonObject.getLong("supinfoId"));
            dataItem.setProdinfoRemark(jsonObject.getString("prodinfoRemark"));
            dataItems.add(dataItem);
        }
        log.info("分页:{},数据量:{}", pageNum, dataItems.size());
        return dataItems;
    }

    public void saveDataToDatabase(List<DataItem> data) {
        log.info("开始保存数据,数据量:{}", data.size());
        if (!data.isEmpty()) {
            log.info("开始插入数据");
            // 批量插入数据
            boolean flag = dataItemService.saveBatch(data);
            log.info("数据插入完成");
//            dataItemMapper.insertBatchSomeColumn(data);
        }
    }

    private int getTotalDataCount(String token) {
        // 调用接口获取总数据量
        String apiUrl = "http://10.210.31.9:9033/apis/open/esi/smpcsmc/qrySupplierProdListDataLake";
        HttpHeaders headers = new HttpHeaders();
//        String token = null;
//        try {
//            token = new String(Files.readAllBytes(Paths.get("/opt/software/etlforeign/token/token.txt"))).trim();
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_JSON);

        JSONObject request = new JSONObject();
        request.put("extOid", 1);
        request.put("clientId", "117158@118092");
        request.put("pageNo", 1);
        request.put("pageSize", 1);
        HttpEntity<String> entity = new HttpEntity<>(request.toString(), headers);
        String responseJson = restTemplate.postForObject(apiUrl, entity, String.class);
        JSONObject response = new JSONObject(responseJson);
        System.out.println(response);
        return response.getJSONObject("data").getInt("recordsTotal");
    }

    private int getTotalDataCount1(String token) {
        // 调用接口获取总数据量
        String apiUrl = "http://10.210.31.9:9033/apis/open/esi/smpcsmc/qrySupplierListDataLake";
        HttpHeaders headers = new HttpHeaders();
//        String token = null;
//        try {
//            token = new String(Files.readAllBytes(Paths.get("/opt/software/etlforeign/token/token.txt"))).trim();
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_JSON);

        JSONObject request = new JSONObject();
        request.put("extOid", 1);
        request.put("clientId", "117158@118092");
        request.put("pageNo", 1);
        request.put("pageSize", 1);
        HttpEntity<String> entity = new HttpEntity<>(request.toString(), headers);
        String responseJson = restTemplate.postForObject(apiUrl, entity, String.class);
        JSONObject response = new JSONObject(responseJson);
        System.out.println(response);
        return response.getJSONObject("data").getInt("recordsTotal");
    }

    private void updateEtlDate(int type) {
        // 获取前一天的日期
        LocalDate yesterday = LocalDate.now().minusDays(1);
        String etlDate = yesterday.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        if (type == 0) {
            // 更新 ETL 日期
            LambdaQueryWrapper<DataItem> queryWrapper = new LambdaQueryWrapper<>();
//            queryWrapper.eq(DataItem::getEtlDate, LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            queryWrapper.isNull(DataItem::getEtlDate);
            queryWrapper.isNotNull(DataItem::getId);
            DataItem dataItem = new DataItem();
            dataItem.setEtlDate(etlDate);
            dataItemService.update(dataItem, queryWrapper);
        } else {
            // 更新 ETL 日期
            LambdaQueryWrapper<DataItem1> queryWrapper = new LambdaQueryWrapper<>();
//            queryWrapper.eq(DataItem1::getEtlDate, LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            queryWrapper.isNull(DataItem1::getEtlDate);
            queryWrapper.isNotNull(DataItem1::getId);
            DataItem1 dataItem = new DataItem1();
            dataItem.setEtlDate(etlDate);
            dataItem1Service.update(dataItem, queryWrapper);
        }
//        // 更新 ETL 日期
//        LambdaQueryWrapper<DataItem> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.isNotNull(DataItem::getId);
//        DataItem dataItem = new DataItem();
//        dataItem.setEtlDate(etlDate);
//        dataItemService.update(dataItem, queryWrapper);
//        dataItemMapper.update(dataItem, queryWrapper);
//        dataItemMapper.update(queryWrapper);
//        dataItemMapper.updateEtlDate(etlDate);
    }
    @Async
    public void fetchDataAndSave1() {

        // 1. 清空表
        LambdaQueryWrapper<DataItem1> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DataItem1::getEtlDate, LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        queryWrapper.isNotNull(DataItem1::getId);
        dataItem1Service.remove(queryWrapper);
        // 2. 获取token
        AtomicReference<String> token = new AtomicReference<>();
//        try {
//            token.set(new String(Files.readAllBytes(Paths.get("/opt/software/etlforeign/token/token.txt"))).trim());
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
        token.set(tokenService.getToken("", null));
        // 3. 获取接口的总记录数
        int totalData = getTotalDataCount1(token.get());
        int totalPages = (totalData + PAGE_SIZE - 1) / PAGE_SIZE;

        // 4. 创建并发任务
        List<Callable<Void>> tasks = new ArrayList<>();
        for (int page = 1; page <= totalPages; page++) {
            final int pageNum = page;
            tasks.add(() -> {
                // 5. 分页获取数据
                log.info("开始添加任务,分页:{},数据量:{},总页数:{}", pageNum, totalData, totalPages);
                List<DataItem1> data = fetchDataFromAPI1(pageNum, PAGE_SIZE, token.get());
                log.info("data:{}", data);
                // 6. 保存数据到数据库
                dataItem1Service.saveDataToDatabase(data, pageNum);
                log.info("任务完成,分页:{}", pageNum);
                return null;
            });
        }

        try {
            log.info("开始执行任务");
            // 7. 执行所有任务
            executorService.invokeAll(tasks);

            // 8. 所有任务完成后更新ETL日期
            updateEtlDate(1);
            log.info("任务执行结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private List<DataItem1> fetchDataFromAPI1(int pageNum, int pageSize, String token) {
        String apiUrl = "http://10.210.31.9:9033/apis/open/esi/smpcsmc/qrySupplierListDataLake";
        HttpHeaders headers = new HttpHeaders();

        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_JSON);

        JSONObject request = new JSONObject();
        request.put("extOid", 1);
        request.put("clientId", "117158@118092");
        request.put("pageNo", pageNum);
        request.put("pageSize", pageSize);
        HttpEntity<String> entity = new HttpEntity<>(request.toString(), headers);
        String responseJson = restTemplate.postForObject(apiUrl, entity, String.class);
        JSONObject response = new JSONObject(responseJson);
//        System.out.println(response);
        JSONArray rows = response.getJSONObject("data").getJSONArray("rows");
        System.out.println(rows.length()+"********************************");
        // 将返回的JSON数据转换为DataItem列表
        List<DataItem1> dataItems = null;
        try {
            dataItems = new ArrayList<>();
            for (int i = 0; i < rows.length(); i++) {
                JSONObject jsonObject = rows.getJSONObject(i);
                DataItem1 dataItem = new DataItem1();
                dataItem.setSupinfoId(jsonObject.optLong("supinfoId", 0L));
                log.info("supinfoId: {}", jsonObject.optLong("supinfoId", 0L));
                dataItem.setAgentQualify(jsonObject.optString("agentQualify", ""));
                log.info("agentQualify: {}", jsonObject.optString("agentQualify", ""));
                dataItem.setAreaName(jsonObject.optString("areaName", ""));
                log.info("areaName: {}", jsonObject.optString("areaName", ""));
                dataItem.setBankId(jsonObject.optString("bankId", ""));
                log.info("bankId: {}", jsonObject.optString("bankId", ""));
                dataItem.setBankName(jsonObject.optString("bankName", ""));
                log.info("bankName: {}", jsonObject.optString("bankName", ""));
                dataItem.setBelongCompanyId(jsonObject.optString("belongCompanyId", ""));
                log.info("belongCompanyId: {}", jsonObject.optString("belongCompanyId", ""));
                dataItem.setBelongCompanyName(jsonObject.optString("belongCompanyName", ""));
                log.info("belongCompanyName: {}", jsonObject.optString("belongCompanyName", ""));
                dataItem.setBusiScope(jsonObject.optString("busiScope", ""));
                log.info("busiScope: {}", jsonObject.optString("busiScope", ""));
                dataItem.setBusinessEnd(jsonObject.optString("businessEnd", ""));
                log.info("businessEnd: {}", jsonObject.optString("businessEnd", ""));
                dataItem.setBusinessStart(jsonObject.optString("businessStart", ""));
                log.info("businessStart: {}", jsonObject.optString("businessStart", ""));
                dataItem.setBusinessValidDateStr(jsonObject.optString("businessValidDateStr", ""));
                log.info("businessValidDateStr: {}", jsonObject.optString("businessValidDateStr", ""));
                dataItem.setCapacity(jsonObject.optString("capacity", ""));
                log.info("capacity: {}", jsonObject.optString("capacity", ""));
                dataItem.setCityCode(jsonObject.optString("cityCode", ""));
                log.info("cityCode: {}", jsonObject.optString("cityCode", ""));
                dataItem.setCityName(jsonObject.optString("cityName", ""));
                log.info("cityName: {}", jsonObject.optString("cityName", ""));
                dataItem.setCompanyProfile(jsonObject.optString("companyProfile", ""));
                log.info("companyProfile: {}", jsonObject.optString("companyProfile", ""));
                dataItem.setCompanyType(jsonObject.optString("companyType", ""));
                log.info("companyType: {}", jsonObject.optString("companyType", ""));
                dataItem.setCompanyTypeName(jsonObject.optString("companyTypeName", ""));
                log.info("companyTypeName: {}", jsonObject.optString("companyTypeName", ""));
                dataItem.setContactEmail(jsonObject.optString("contactEmail", ""));
                log.info("contactEmail: {}", jsonObject.optString("contactEmail", ""));
                dataItem.setContactFax(jsonObject.optString("contactFax", ""));
                log.info("contactFax: {}", jsonObject.optString("contactFax", ""));
                dataItem.setContactMobile(jsonObject.optString("contactMobile", ""));
                log.info("contactMobile: {}", jsonObject.optString("contactMobile", ""));
                dataItem.setContactName(jsonObject.optString("contactName", ""));
                log.info("contactName: {}", jsonObject.optString("contactName", ""));
                dataItem.setContactTel(jsonObject.optString("contactTel", ""));
                log.info("contactTel: {}", jsonObject.optString("contactTel", ""));
                dataItem.setCooperEnterprise(jsonObject.optString("cooperEnterprise", ""));
                log.info("cooperEnterprise: {}", jsonObject.optString("cooperEnterprise", ""));
                dataItem.setCooperPerformIccec(jsonObject.optString("cooperPerformIccec", ""));
                log.info("cooperPerformIccec: {}", jsonObject.optString("cooperPerformIccec", ""));
                dataItem.setCooperPerformSameInd(jsonObject.optString("cooperPerformSameInd", ""));
                log.info("cooperPerformSameInd: {}", jsonObject.optString("cooperPerformSameInd", ""));
                dataItem.setCountryCode(jsonObject.optString("countryCode", ""));
                log.info("countryCode: {}", jsonObject.optString("countryCode", ""));
                dataItem.setCountryName(jsonObject.optString("countryName", ""));
                log.info("countryName: {}", jsonObject.optString("countryName", ""));
                dataItem.setCountyCode(jsonObject.optString("countyCode", ""));
                log.info("countyCode: {}", jsonObject.optString("countyCode", ""));
                dataItem.setCountyName(jsonObject.optString("countyName", ""));
                log.info("countyName: {}", jsonObject.optString("countyName", ""));
                dataItem.setCreateTime(jsonObject.optString("createTime", ""));
                log.info("createTime: {}", jsonObject.optString("createTime", ""));
                dataItem.setFactCapl(jsonObject.optString("factCapl", ""));
                log.info("factCapl: {}", jsonObject.optString("factCapl", ""));
                dataItem.setFoundTime(jsonObject.optString("foundTime", ""));
                log.info("foundTime: {}", jsonObject.optString("foundTime", ""));
                dataItem.setHomeAddr(jsonObject.optString("homeAddr", ""));
                log.info("homeAddr: {}", jsonObject.optString("homeAddr", ""));
                dataItem.setIsInIndy(jsonObject.optLong("isInIndy", 0L));
                log.info("isInIndy: {}", jsonObject.optLong("isInIndy", 0L));
                dataItem.setIsOutSup(jsonObject.optLong("isOutSup", 0L));
                log.info("isOutSup: {}", jsonObject.optLong("isOutSup", 0L));
                dataItem.setLegalContactEmail(jsonObject.optString("legalContactEmail", ""));
                log.info("legalContactEmail: {}", jsonObject.optString("legalContactEmail", ""));
                dataItem.setLegalContactName(jsonObject.optString("legalContactName", ""));
                log.info("legalContactName: {}", jsonObject.optString("legalContactName", ""));
                dataItem.setLocationCode(jsonObject.optString("locationCode", ""));
                log.info("locationCode: {}", jsonObject.optString("locationCode", ""));
                dataItem.setLocationName(jsonObject.optString("locationName", ""));
                log.info("locationName: {}", jsonObject.optString("locationName", ""));
                dataItem.setMaindataSupCode(jsonObject.optString("maindataSupCode", ""));
                log.info("maindataSupCode: {}", jsonObject.optString("maindataSupCode", ""));
                dataItem.setOfficeAddr(jsonObject.optString("officeAddr", ""));
                log.info("officeAddr: {}", jsonObject.optString("officeAddr", ""));
                dataItem.setOrgCode(jsonObject.optString("orgCode", ""));
                log.info("orgCode: {}", jsonObject.optString("orgCode", ""));
                dataItem.setOrgCredentialsEnd(jsonObject.optString("orgCredentialsEnd", ""));
                log.info("orgCredentialsEnd: {}", jsonObject.optString("orgCredentialsEnd", ""));
                dataItem.setOrgCredentialsStart(jsonObject.optString("orgCredentialsStart", ""));
                log.info("orgCredentialsStart: {}", jsonObject.optString("orgCredentialsStart", ""));
                dataItem.setOrgCredentialsValidDate(jsonObject.optString("orgCredentialsValidDate", ""));
                log.info("orgCredentialsValidDate: {}", jsonObject.optString("orgCredentialsValidDate", ""));
                dataItem.setOrgStructMarketNet(jsonObject.optString("orgStructMarketNet", ""));
                log.info("orgStructMarketNet: {}", jsonObject.optString("orgStructMarketNet", ""));
                dataItem.setProcessTech(jsonObject.optString("processTech", ""));
                log.info("processTech: {}", jsonObject.optString("processTech", ""));
                dataItem.setProducerName(jsonObject.optString("producerName", ""));
                log.info("producerName: {}", jsonObject.optString("producerName", ""));
                dataItem.setProvinceCode(jsonObject.optString("provinceCode", ""));
                log.info("provinceCode: {}", jsonObject.optString("provinceCode", ""));
                dataItem.setProvinceName(jsonObject.optString("provinceName", ""));
                log.info("provinceName: {}", jsonObject.optString("provinceName", ""));
                dataItem.setRecommendIndy4A(jsonObject.optString("recommendIndy4A", ""));
                log.info("recommendIndy4A: {}", jsonObject.optString("recommendIndy4A", ""));
                dataItem.setRecommendIndyCode(jsonObject.optString("recommendIndyCode", ""));
                log.info("recommendIndyCode: {}", jsonObject.optString("recommendIndyCode", ""));
                dataItem.setRecommendIndyId(String.valueOf(jsonObject.optLong("recommendIndyId", 0L)));
                log.info("recommendIndyId: {}", jsonObject.optLong("recommendIndyId", 0L));
                dataItem.setRecommendIndyName(jsonObject.optString("recommendIndyName", ""));
                log.info("recommendIndyName: {}", jsonObject.optString("recommendIndyName", ""));
                dataItem.setRegCapl(jsonObject.optString("regCapl", ""));
                log.info("regCapl: {}", jsonObject.optString("regCapl", ""));
                dataItem.setRegNum(jsonObject.optString("regNum", ""));
                log.info("regNum: {}", jsonObject.optString("regNum", ""));
                dataItem.setRegistMobile(jsonObject.optString("registMobile", ""));
                log.info("registMobile: {}", jsonObject.optString("registMobile", ""));
                dataItem.setSalesHeaderName(jsonObject.optString("salesHeaderName", ""));
                log.info("salesHeaderName: {}", jsonObject.optString("salesHeaderName", ""));
                dataItem.setSupCode(jsonObject.optString("supCode", ""));
                log.info("supCode: {}", jsonObject.optString("supCode", ""));
                dataItem.setSupName(jsonObject.optString("supName", ""));
                log.info("supName: {}", jsonObject.optString("supName", ""));
                dataItem.setSupShort(jsonObject.optString("supShort", ""));
                log.info("supShort: {}", jsonObject.optString("supShort", ""));
                dataItem.setSupSubType(jsonObject.optString("supSubType", ""));
                log.info("supSubType: {}", jsonObject.optString("supSubType", ""));
                dataItem.setSupType(jsonObject.optString("supType", ""));
                log.info("supType: {}", jsonObject.optString("supType", ""));
                dataItem.setTaxCode(jsonObject.optString("taxCode", ""));
                log.info("taxCode: {}", jsonObject.optString("taxCode", ""));
                dataItem.setUnifyCode(jsonObject.optString("unifyCode", ""));
                log.info("unifyCode: {}", jsonObject.optString("unifyCode", ""));
                dataItem.setUpdateTime(jsonObject.optString("updateTime", ""));
                log.info("updateTime: {}", jsonObject.optString("updateTime", ""));
                dataItem.setWebsite(jsonObject.optString("website", ""));
                log.info("website: {}", jsonObject.optString("website", ""));
                dataItems.add(dataItem);
                System.out.println(dataItem+"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
            }
            log.info("分页:{},数据量:{}", pageNum, dataItems.size());
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        return dataItems;
    }
}
